package com.cloudlinkscm.loms.services.base.notify.domain;

import com.cloudlinkscm.loms.services.base.notify.constant.SendStatusEnum;
import com.cloudlinkscm.loms.services.base.notify.dao.AbstractMessageDao;
import com.cloudlinkscm.loms.services.base.notify.domain.notifier.AbstractNotifier;
import com.cloudlinkscm.loms.services.base.notify.dto.SendResultDto;
import com.cloudlinkscm.loms.services.base.notify.exception.MessageNotFoundException;
import com.cloudlinkscm.loms.services.base.notify.model.Notification;
import com.cloudlinkscm.loms.services.base.notify.model.NotificationResult;
import com.cloudlinkscm.loms.services.base.notify.model.entity.Message;
import com.github.pagehelper.PageInfo;

/**
 * 抽象的消息({@link Message})管理器
 *
 * @see AbstractMessageDao
 * @see AbstractNotifier
 * @see AbstractMessageFlowManager
 * @author : tac
 * @date : 2017/6/16
 */
public abstract class AbstractMessageManager<MESSAGE extends Message> {
    private AbstractMessageDao<MESSAGE> dao;
    private AbstractNotifier<MESSAGE, ? extends Notification, ? extends  NotificationResult> defaultNotifier;
    private AbstractMessageFlowManager<MESSAGE> messageFlowManager;

    public AbstractMessageManager(
            AbstractMessageDao<MESSAGE> dao,
            AbstractNotifier<MESSAGE, ? extends Notification, ? extends NotificationResult> defaultNotifier,
            AbstractMessageFlowManager<MESSAGE> messageFlowManager) {
        this.dao = dao;
        this.defaultNotifier = defaultNotifier;
        this.messageFlowManager = messageFlowManager;
    }

    /**
     * 为具体的消息种类产生一条新的消息记录
     */
    public String newMessage(MESSAGE message) {
        if (dao.insert(message) > 0) {
            return message.getId();
        }
        return null;
    }

    /**
     * 发送一条消息
     *
     * <p>
     *     发送完后无论成功失败均会写一条消息流水记录
     * </p>
     *
     */
    public SendResultDto send(MESSAGE message){
        SendResultDto resultDto = defaultNotifier.send(message);
        messageFlowManager.insert(message, resultDto);
        return resultDto;
    }

    public abstract PageInfo<MESSAGE> listMessage4Send(int num);

    /**
     * 判断是否需要立即发送
     */
    public abstract boolean isSendNow(MESSAGE message);

    /**
     * 设置消息状态
     */
    public int setStatus(String id, SendStatusEnum status){
        return setStatus(id, status.val);
    }

    public abstract int setStatus(String id, Integer status);

    /**
     * 发送失败次数加一
     */
    public int plusOneResendNum(String id){
        MESSAGE message = dao.selectByPrimaryKey(id);
        if(message == null){
            throw new MessageNotFoundException();
        }
        MESSAGE o;
        try {
            o = (MESSAGE) message.getClass().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        o.setId(id);
        o.setResendNum(message.getResendNum() + 1);
        return dao.updateByPrimaryKeySelective(o);
    }
}
